#include "../include/GPIO.h"
#include <iostream>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <stdbool.h>


using namespace std;


int GPIO::do_map() {
    int file_descriptor;
    if ((file_descriptor = open("/dev/mem", O_RDWR|O_SYNC)) < 0) {
        cout << "Failed to open /dev/mem, try checking permissions." << endl;
        return -1;
    }

    mmap_retval = mmap(
       NULL,
       (size_t) IO_access::BLOCK_SIZE,
       PROT_READ|PROT_WRITE,
       MAP_SHARED,
       file_descriptor,             // Contains flags returned by 'open'
       (off_t) IO_access::GPIO_BASE // Address in physical map that we want this memory block to expose
    );


    if (mmap_retval == MAP_FAILED) {
        cout << "failed with errno " << errno << endl;
        perror("mmap");
        return -1;
    }

    addr = (volatile uintptr_t *)mmap_retval;

    return (0);
}


volatile unsigned int * GPIO::get_addr() {
    return (addr);
}

void GPIO::config_as_input(gpio_names gpio_name) {
    *(addr + (int32)(gpio_name / 10.0)) &= ~(7 << (int32)((gpio_name % 10) * 3.0));
}

void GPIO::config_as_output(gpio_names gpio_name) {
    *(addr + (int32)(gpio_name / 10.0)) = (*(addr + (int32)(gpio_name / 10.0)) & ~(7 << (int32)((gpio_name % 10) * 3.0))) | (1 << (int32)((gpio_name % 10) * 3.0));
}
